﻿// This File is part of Innovation Foundry's "QualityHelper Project"
//
// Copyright  2009 Innovation Foundry Pty Ltd
// All rights reserved
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA  02110-1301 USA
// or alternatively it may be downloaded from <http://www.gnu.org/licenses/>.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;
using System.Collections.Generic;
using System.Windows.Browser;
using System.Linq;
using System.ComponentModel;
using System.Collections.ObjectModel;

using InnovationFoundry.QualityHelper.Silverlight.BLL.Objects;

namespace InnovationFoundry.QualityHelper.Silverlight.BLL
{
    public static class ParserHelper
    {
        public static DiagramObject ParseDiagram(object diagram)
        {
            try
            {
                ScriptObject _jobject = diagram as ScriptObject;
                ScriptObject _procRoot = (_jobject.GetProperty("procedureRoot") as ScriptObject) as ScriptObject;
                ScriptObject _procedures = (_jobject.GetProperty("procedures") as ScriptObject) as ScriptObject;
                ScriptObject _connections = (_jobject.GetProperty("connections") as ScriptObject) as ScriptObject;


                DiagramObject dg = new DiagramObject();
                dg.Procedures = ParseProcedures(_procedures);
                dg.Connections = (_connections != null) ? ParseConnections(_connections, dg.Procedures) : new ObservableCollection<ConnectionObject>();
                dg.ProcedureRoot = (_procRoot != null) ? ParseProcedure(_procRoot) : null;
                dg.Title = (dg.ProcedureRoot == null) ? "" : dg.ProcedureRoot.ProcedureName;
                dg.DiagramID = _jobject.GetProperty("diagramID") as string;

                return dg;
            }
            catch
            {
                return null;
            }
        }

        public static ObservableCollection<DocumentObject> ParseDocuments(ScriptObject _documents)
        {
            ObservableCollection<DocumentObject> result = new ObservableCollection<DocumentObject>();
            int length = int.Parse(_documents.GetProperty("length").ToString());
            for (int i = 0; i < length; i++)
            {
                ScriptObject docObj = ((ScriptObject)_documents.GetProperty(i));
                DocumentObject doc = new DocumentObject();
                doc.DateUpdated = long.Parse(docObj.GetProperty("dateUpdated").ToString());
                doc.DocumentDescription = string.Format("{0}",docObj.GetProperty("documentDescription"));
                doc.DocumentExtension =  string.Format("{0}",docObj.GetProperty("documentExtension"));
                doc.DocumentID = long.Parse(docObj.GetProperty("documentID").ToString());
                doc.DocumentName = string.Format("{0}",docObj.GetProperty("documentName"));
                doc.ImageURL = string.Format("{0}",docObj.GetProperty("imageURL"));
                doc.Md5Checksum = string.Format("{0}",docObj.GetProperty("md5Checksum"));
                doc.OriginURL = string.Format("{0}",docObj.GetProperty("originURL"));
                result.Add(doc);
            }
            return result;
        }

        public static ObservableCollection<ConnectionObject> ParseConnections(ScriptObject _connections, ObservableCollection<ProcedureObject> procedures)
        {
            ObservableCollection<ConnectionObject> result = new ObservableCollection<ConnectionObject>();

            int length = int.Parse(_connections.GetProperty("length").ToString());
            for (int i = 0; i < length; i++)
            {
                ScriptObject connObj = ((ScriptObject)_connections.GetProperty(i));
                ConnectionObject conn = new ConnectionObject();
                conn.ConnectionType = new ConnectionTypeObject();

                try
                {
                    if (procedures != null)
                    {
                        conn.ProcedureDestination = procedures.First(p => p.ProcedureID == string.Format("{0}", connObj.GetProperty("destination")));
                        conn.ProcedureOrigin = procedures.First(p => p.ProcedureID == string.Format("{0}", connObj.GetProperty("origin")));
                    }
                    else
                    {
                        conn.ProcedureDestination = new ProcedureObject(string.Format("{0}", connObj.GetProperty("destination")), null, null, null, null);
                        conn.ProcedureOrigin = new ProcedureObject(string.Format("{0}", connObj.GetProperty("origin")), null, null, null, null);
                    }
                }
                catch
                {
                    conn.ProcedureDestination = new ProcedureObject(null, null, null, null, null);
                    conn.ProcedureOrigin = new ProcedureObject(string.Format("{0}", connObj.GetProperty("origin")), null, null, null, null);
                }

                try
                {
                    conn.ConnectionType.ColorRGBHex = ((ScriptObject)connObj.GetProperty("connectionType")).GetProperty("colorRGBHex").ToString();
                    conn.ConnectionType.ConnectionTypeName = ((ScriptObject)connObj.GetProperty("connectionType")).GetProperty("connectionTypeName").ToString();
                }
                catch (Exception ex)
                {
                    conn.ConnectionType.ColorRGBHex = "000000";
                    conn.ConnectionType.ConnectionTypeName = string.Empty;
                }
                result.Add(conn);
            }
            for (int i = result.Count - 1; i > -1; i--)
            {
                int resultCount = result.Count(c => c.ProcedureDestination.ID == result[i].ProcedureDestination.ID && c.ProcedureOrigin.ID == result[i].ProcedureOrigin.ID && c.ConnectionType.ConnectionTypeName == result[i].ConnectionType.ConnectionTypeName);
                if (resultCount > 1)
                    result.RemoveAt(i);
            }
            return result;
        }

        public static ProcedureObject ParseProcedure(ScriptObject _procedure)
        {

                ScriptObject procObj = ((ScriptObject)_procedure);
                ProcedureObject proc = new ProcedureObject();
                //Initialize Nested Types
                proc.Purpose = new PurposeObject();
                proc.ProcedureDescription = string.Format("{0}",procObj.GetProperty("procedureDescription"));
                proc.ProcedureName = string.Format("{0}",procObj.GetProperty("procedureName"));
                proc.ProcedureID = string.Format("{0}",procObj.GetProperty("procedureID"));


                //Set Nested Objects now
                //Groups
                ScriptObject procGroups = procObj.GetProperty("groups") as ScriptObject;
                int lengthGroups = int.Parse(procGroups.GetProperty("length").ToString());
                for (int j = 0; j < lengthGroups; j++)
                {
                    ScriptObject procGroup = ((ScriptObject)procGroups.GetProperty(j));
                    proc.Groups.Add(new ProcedureGroupObject(string.Format("{0}",procGroup.GetProperty("groupName")), proc.ProcedureID));
                }
                //Aliases
                ScriptObject procAliases = procObj.GetProperty("aliases") as ScriptObject;
                int lengthAliases = int.Parse(procAliases.GetProperty("length").ToString());
                for (int k = 0; k < lengthAliases; k++)
                {
                    proc.Aliases.Add(new ProcedureAliasesObject(procAliases.GetProperty(k).ToString(), proc.ProcedureID));
                }
                //InboundReferences
                ScriptObject procInboundReferences = procObj.GetProperty("inboundReferences") as ScriptObject;
                int lengthInboundReferences = int.Parse(procInboundReferences.GetProperty("length").ToString());
                for (int l = 0; l < lengthInboundReferences; l++)
                {
                    proc.InboundReferences.Add(new ReferenceObject(string.Format("{0}", ((ScriptObject)procInboundReferences.GetProperty(l)).GetProperty("origin")), proc.ProcedureID));
                }
                //OutboundReferences
                ScriptObject procOutboundReferences = procObj.GetProperty("outboundReferences") as ScriptObject;
                int lengthOutboundReferences = int.Parse(procOutboundReferences.GetProperty("length").ToString());
                for (int m = 0; m < lengthOutboundReferences; m++)
                {
                    proc.OutboundReferences.Add(new ReferenceObject(proc.ProcedureID, string.Format("{0}", ((ScriptObject)procOutboundReferences.GetProperty(m)).GetProperty("destination"))));
                }

                ScriptObject procPurpose = procObj.GetProperty("purpose") as ScriptObject;
                proc.Purpose.FlowchartElement = string.Format("{0}",procPurpose.GetProperty("flowchartElement"));
                proc.Purpose.PurposeName = string.Format("{0}",procPurpose.GetProperty("purposeName"));
                return proc;

        }

        public static ObservableCollection<ProcedureObject> ParseProcedures(ScriptObject _procedures)
        {
            ObservableCollection<ProcedureObject> result = new ObservableCollection<ProcedureObject>();
            if (_procedures == null)
                return result;
            int length = int.Parse(_procedures.GetProperty("length").ToString());
            for (int i = 0; i < length; i++)
            {
                ScriptObject procObj = ((ScriptObject)_procedures.GetProperty(i));
                result.Add(ParseProcedure(procObj));
            }
            return result;
        }

        
    }


}
